package com.example.aop;

import com.alibaba.fastjson.JSONObject;
import com.example.mapper.OperateLogMapper;
import com.example.pojo.OperateLog;
import com.example.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class LogAspect {

//    @Autowired
//    private ApplicationContext applicationContext;                                    //IOC容器对象
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(com.example.anno.Log)")                                        //加了该注解的方法，都会成AOP，
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {

        /**
         * 该aop方法对应数据库的 tb_operate_log 表
         * 记录了：
         * 操作着的主键id，操作着的姓名，操作着的学号，操作具体时间，操作的类名，操作的方法名，传进的方法参数，返回的方法参数，操作消耗时间
         */
        String JWT = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(JWT);
        Integer operateUserId = (Integer) claims.get("id");                             //操作人主键
        String name = (String) claims.get("name");                                      //操作人姓名
        String studentID = (String) claims.get("studentID");                            //操作人学号
        LocalDateTime operateTime =  LocalDateTime.now();                               //操作时间
        String className = joinPoint.getTarget().getClass().getName();                  //操作类名：getTarget()拿到目标对象，getClass()拿到类对象，getName()拿到类名
        String methodName = joinPoint.getSignature().getName();                         //操作方法名：getSignature()，获取到方法签名
        String methodParams = Arrays.toString(joinPoint.getArgs());                     //操作方法参数

        long begin = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();                                           //调用原始目标方法执行
        long end = System.currentTimeMillis();
        String returnValue = JSONObject.toJSONString(proceed);                          //方法返回值
        long costTime = end - begin;                                                    //操作耗时

        OperateLog operateLog = new OperateLog(null,operateUserId,name,studentID,operateTime,className,methodName,methodParams,returnValue,costTime);

        operateLogMapper.insert(operateLog);
        return proceed;
    }
}
